#include "./winupdate.h"
#include "miniui/minitype.h"

using namespace MiniUI;

UpdateWindow::UpdateWindow()
: m_pfnUpdateLayered(nullptr)
{
    m_hUser32 = LoadLibrary(_T("User32.dll"));
    m_pfnUpdateLayered = (PF_UpdateLayeredWindowIndirect)GetProcAddress(m_hUser32, "UpdateLayeredWindowIndirect");
}

UpdateWindow::~UpdateWindow()
{
    m_pfnUpdateLayered = nullptr;
    ::FreeLibrary(m_hUser32);
}

BOOL UpdateWindow::Update(HWND hWnd, HDC hdcDst, HDC hdcSrc, LPRECT lpRcDirty, BYTE Alpha)
{
    if (::IsIconic(hWnd))
    {
        return TRUE;
    }

    RECT rcWin = {0, 0, 0, 0};
    GetWindowRect(hWnd, &rcWin);

    const RECT* lpRcWin = &rcWin;

    BLENDFUNCTION blend;

    blend.BlendOp = AC_SRC_OVER;
    blend.BlendFlags = 0;
    blend.AlphaFormat = AC_SRC_ALPHA;
    blend.SourceConstantAlpha = Alpha;

    POINT ptSrc = {0, 0};
    POINT ptWinPos = {lpRcWin->left, lpRcWin->top};
    SIZE szWin = {lpRcWin->right - lpRcWin->left, lpRcWin->bottom - lpRcWin->top};

    BOOL bRet = FALSE;

    if (m_pfnUpdateLayered)
    {
        UPDATELAYEREDWINDOWINFO ULWInfo;
        ULWInfo.cbSize = sizeof(ULWInfo);
        ULWInfo.hdcDst = hdcDst;
        ULWInfo.pptDst = &ptWinPos;
        ULWInfo.psize = &szWin;
        ULWInfo.hdcSrc = hdcSrc;
        ULWInfo.pptSrc = &ptSrc;
        ULWInfo.crKey = 0;
        ULWInfo.pblend = &blend;
        ULWInfo.dwFlags = ULW_ALPHA;
        ULWInfo.prcDirty = lpRcDirty;

        bRet = m_pfnUpdateLayered(hWnd, &ULWInfo);
    }
    else
    {
        bRet = ::UpdateLayeredWindow(hWnd, hdcDst, &ptWinPos, &szWin, hdcSrc, &ptSrc, 0, &blend, ULW_ALPHA);
    }

    if (!bRet)
    {
        int err = GetLastError();
    }

    return bRet;
}